import mongoose from 'mongoose';
import { RolePermission, IRolePermission, IRolePermissionDocument } from '../models/rolePermission';

/**
 * 角色权限关联数据访问对象
 * 提供角色权限关联相关的数据库操作方法
 */
export class RolePermissionDAO {
  /**
   * 创建新的角色权限关联
   * @param rolePermissionData 角色权限关联数据
   * @returns 创建的角色权限关联文档
   */
  async create(rolePermissionData: Partial<IRolePermission>): Promise<IRolePermissionDocument> {
    try {
      const rolePermission = new RolePermission(rolePermissionData);
      return await rolePermission.save();
    } catch (error: any) {
      if (error.code === 11000) {
        // 处理唯一性约束错误
        throw new Error('Role permission assignment already exists');
      }
      throw error;
    }
  }

  /**
   * 根据ID查找角色权限关联
   * @param id 角色权限关联ID
   * @returns 角色权限关联文档或null
   */
  async findById(id: mongoose.Types.ObjectId | string): Promise<IRolePermissionDocument | null> {
    try {
      if (!id) {
        throw new Error('RolePermission ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的ID');
      }
      
      return await RolePermission.findById(id)
        .populate('roleId')
        .populate('permissionId')
        .populate('systemId')
        .populate('assignedBy');
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据角色ID查找权限关联
   * @param roleId 角色ID
   * @param systemId 系统ID（可选）
   * @returns 角色权限关联文档数组
   */
  async findByRoleId(
    roleId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IRolePermissionDocument[]> {
    try {
      if (!roleId) {
        throw new Error('Role ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(roleId)) {
        throw new Error('无效的角色ID');
      }
      
      const roleObjectId = typeof roleId === 'string' ? new mongoose.Types.ObjectId(roleId) : roleId;
      let systemObjectId: mongoose.Types.ObjectId | undefined;
      
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('无效的系统ID');
        }
        systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      }
      
      const query: any = { roleId: roleObjectId, status: 1 };
      if (systemObjectId) {
        query.systemId = systemObjectId;
      }
      
      return await RolePermission.find(query)
        .populate('permissionId')
        .populate('systemId')
        .populate('assignedBy')
        .sort({ createdAt: -1 });
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据权限ID查找角色关联
   * @param permissionId 权限ID
   * @param systemId 系统ID（可选）
   * @returns 角色权限关联文档数组
   */
  async findByPermissionId(
    permissionId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<IRolePermissionDocument[]> {
    try {
      if (!permissionId) {
        throw new Error('Permission ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(permissionId)) {
        throw new Error('无效的权限ID');
      }
      
      const permissionObjectId = typeof permissionId === 'string' ? new mongoose.Types.ObjectId(permissionId) : permissionId;
      let systemObjectId: mongoose.Types.ObjectId | undefined;
      
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('无效的系统ID');
        }
        systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      }
      
      const query: any = { permissionId: permissionObjectId, status: 1 };
      if (systemObjectId) {
        query.systemId = systemObjectId;
      }
      
      return await RolePermission.find(query)
        .populate('roleId')
        .populate('systemId')
        .populate('assignedBy')
        .sort({ createdAt: -1 });
    } catch (error) {
      throw error;
    }
  }

  /**
   * 根据系统ID查找角色权限关联
   * @param systemId 系统ID
   * @returns 角色权限关联文档数组
   */
  async findBySystemId(systemId: mongoose.Types.ObjectId | string): Promise<IRolePermissionDocument[]> {
    try {
      if (!systemId) {
        throw new Error('System ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(systemId)) {
        throw new Error('无效的系统ID');
      }
      
      const systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      
      return await RolePermission.find({ systemId: systemObjectId, status: 1 })
        .populate('roleId')
        .populate('permissionId')
        .populate('assignedBy')
        .sort({ createdAt: -1 });
    } catch (error) {
      throw error;
    }
  }

  /**
   * 检查角色是否拥有指定权限
   * @param roleId 角色ID
   * @param permissionId 权限ID
   * @param systemId 系统ID（可选）
   * @returns 是否拥有权限
   */
  async hasPermission(
    roleId: mongoose.Types.ObjectId | string,
    permissionId: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<boolean> {
    try {
      if (!roleId) {
        throw new Error('Role ID is required');
      }
      
      if (!permissionId) {
        throw new Error('Permission ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(roleId)) {
        throw new Error('无效的角色ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(permissionId)) {
        throw new Error('无效的权限ID');
      }
      
      const roleObjectId = typeof roleId === 'string' ? new mongoose.Types.ObjectId(roleId) : roleId;
      const permissionObjectId = typeof permissionId === 'string' ? new mongoose.Types.ObjectId(permissionId) : permissionId;
      let systemObjectId: mongoose.Types.ObjectId | undefined;
      
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('无效的系统ID');
        }
        systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      }
      
      return await RolePermission.hasPermission(roleObjectId, permissionObjectId, systemObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量分配权限给角色
   * @param roleId 角色ID
   * @param permissionIds 权限ID数组
   * @param assignedBy 分配人ID
   * @param systemId 系统ID（可选）
   * @param expiresAt 过期时间（可选）
   * @returns 创建的角色权限关联文档数组
   */
  async batchAssign(
    roleId: mongoose.Types.ObjectId | string,
    permissionIds: (mongoose.Types.ObjectId | string)[],
    assignedBy: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string,
    expiresAt?: Date
  ): Promise<IRolePermissionDocument[]> {
    try {
      if (!roleId) {
        throw new Error('Role ID is required');
      }
      
      if (!permissionIds || !Array.isArray(permissionIds) || permissionIds.length === 0) {
        throw new Error('Permission IDs array is required and cannot be empty');
      }
      
      if (!assignedBy) {
        throw new Error('Assigned by user ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(roleId)) {
        throw new Error('无效的角色ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(assignedBy)) {
        throw new Error('Invalid assigned by user ID format');
      }
      
      // 验证所有权限ID格式
      for (const permissionId of permissionIds) {
        if (!mongoose.Types.ObjectId.isValid(permissionId)) {
          throw new Error('存在无效的权限ID');
        }
      }
      
      const roleObjectId = typeof roleId === 'string' ? new mongoose.Types.ObjectId(roleId) : roleId;
      const assignedByObjectId = typeof assignedBy === 'string' ? new mongoose.Types.ObjectId(assignedBy) : assignedBy;
      const permissionObjectIds = permissionIds.map(id => 
        typeof id === 'string' ? new mongoose.Types.ObjectId(id) : id
      );
      
      let systemObjectId: mongoose.Types.ObjectId | undefined;
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('无效的系统ID');
        }
        systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      }
      
      return await RolePermission.batchAssign(
        roleObjectId,
        permissionObjectIds,
        assignedByObjectId,
        systemObjectId,
        expiresAt
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量撤销角色权限
   * @param roleId 角色ID
   * @param permissionIds 权限ID数组
   * @param systemId 系统ID（可选）
   * @returns 撤销的权限数量
   */
  async batchRevoke(
    roleId: mongoose.Types.ObjectId | string,
    permissionIds: (mongoose.Types.ObjectId | string)[],
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<number> {
    try {
      if (!roleId) {
        throw new Error('Role ID is required');
      }
      
      if (!permissionIds || !Array.isArray(permissionIds)) {
        throw new Error('Permission IDs array is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(roleId)) {
        throw new Error('无效的角色ID');
      }
      
      const roleObjectId = typeof roleId === 'string' ? new mongoose.Types.ObjectId(roleId) : roleId;
      
      // 如果权限ID数组为空，撤销角色的所有权限
      if (permissionIds.length === 0) {
        let query: any = { roleId: roleObjectId };
        if (systemId) {
          if (!mongoose.Types.ObjectId.isValid(systemId)) {
            throw new Error('无效的系统ID');
          }
          const systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
          query.systemId = systemObjectId;
        }
        const result = await RolePermission.deleteMany(query);
        return result.deletedCount || 0;
      }
      
      // 验证所有权限ID格式
      for (const permissionId of permissionIds) {
        if (!mongoose.Types.ObjectId.isValid(permissionId)) {
          throw new Error('存在无效的权限ID');
        }
      }
      
      const permissionObjectIds = permissionIds.map(id => 
        typeof id === 'string' ? new mongoose.Types.ObjectId(id) : id
      );
      
      let systemObjectId: mongoose.Types.ObjectId | undefined;
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('无效的系统ID');
        }
        systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      }
      
      return await RolePermission.batchRevoke(roleObjectId, permissionObjectIds, systemObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 删除角色权限关联
   * @param id 角色权限关联ID
   * @returns 是否删除成功
   */
  async delete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!id) {
        throw new Error('RolePermission ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的ID');
      }
      
      const result = await RolePermission.findByIdAndUpdate(
        id,
        { status: 0, updatedAt: new Date() },
        { new: true }
      );
      
      return !!result;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 物理删除角色权限关联
   * @param id 角色权限关联ID
   * @returns 是否删除成功
   */
  async hardDelete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    try {
      if (!id) {
        throw new Error('RolePermission ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的ID');
      }
      
      const result = await RolePermission.findByIdAndDelete(id);
      return !!result;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 更新角色权限关联
   * @param id 角色权限关联ID
   * @param updateData 更新数据
   * @returns 更新后的角色权限关联文档或null
   */
  async update(
    id: mongoose.Types.ObjectId | string,
    updateData: Partial<IRolePermission>
  ): Promise<IRolePermissionDocument | null> {
    try {
      if (!id) {
        throw new Error('RolePermission ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new Error('无效的ID');
      }
      
      // 添加更新时间
      const dataToUpdate = {
        ...updateData,
        updatedAt: new Date()
      };
      
      return await RolePermission.findByIdAndUpdate(
        id,
        dataToUpdate,
        { new: true, runValidators: true }
      ).populate('roleId')
       .populate('permissionId')
       .populate('systemId')
       .populate('assignedBy');
    } catch (error) {
      throw error;
    }
  }

  /**
   * 同步角色权限（替换现有权限）
   * @param roleId 角色ID
   * @param permissionIds 新的权限ID数组
   * @param assignedBy 分配人ID
   * @param systemId 系统ID（可选）
   * @returns 同步结果
   */
  async syncRolePermissions(
    roleId: mongoose.Types.ObjectId | string,
    permissionIds: (mongoose.Types.ObjectId | string)[],
    assignedBy: mongoose.Types.ObjectId | string,
    systemId?: mongoose.Types.ObjectId | string
  ): Promise<{ added: IRolePermissionDocument[]; removed: number }> {
    try {
      if (!roleId) {
        throw new Error('Role ID is required');
      }
      
      if (!permissionIds || !Array.isArray(permissionIds)) {
        throw new Error('Permission IDs array is required');
      }
      
      if (!assignedBy) {
        throw new Error('Assigned by user ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(roleId)) {
        throw new Error('无效的角色ID');
      }
      
      if (!mongoose.Types.ObjectId.isValid(assignedBy)) {
        throw new Error('Invalid assigned by user ID format');
      }
      
      // 验证所有权限ID格式
      for (const permissionId of permissionIds) {
        if (!mongoose.Types.ObjectId.isValid(permissionId)) {
          throw new Error('存在无效的权限ID');
        }
      }
      
      const roleObjectId = typeof roleId === 'string' ? new mongoose.Types.ObjectId(roleId) : roleId;
      const assignedByObjectId = typeof assignedBy === 'string' ? new mongoose.Types.ObjectId(assignedBy) : assignedBy;
      const permissionObjectIds = permissionIds.map(id => 
        typeof id === 'string' ? new mongoose.Types.ObjectId(id) : id
      );
      
      let systemObjectId: mongoose.Types.ObjectId | undefined;
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('Invalid system ID format');
        }
        systemObjectId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      }
      
      return await RolePermission.syncRolePermissions(
        roleObjectId,
        permissionObjectIds,
        assignedByObjectId,
        systemObjectId
      );
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取权限被分配给的角色数量
   * @param permissionId 权限ID
   * @returns 角色数量
   */
  async getPermissionRoleCount(permissionId: mongoose.Types.ObjectId | string): Promise<number> {
    try {
      if (!permissionId) {
        throw new Error('Permission ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(permissionId)) {
        throw new Error('无效的权限ID');
      }
      
      const permissionObjectId = typeof permissionId === 'string' ? new mongoose.Types.ObjectId(permissionId) : permissionId;
      
      return await RolePermission.getPermissionRoleCount(permissionObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取角色拥有的权限数量
   * @param roleId 角色ID
   * @returns 权限数量
   */
  async getRolePermissionCount(roleId: mongoose.Types.ObjectId | string): Promise<number> {
    try {
      if (!roleId) {
        throw new Error('Role ID is required');
      }
      
      if (!mongoose.Types.ObjectId.isValid(roleId)) {
        throw new Error('无效的角色ID');
      }
      
      const roleObjectId = typeof roleId === 'string' ? new mongoose.Types.ObjectId(roleId) : roleId;
      
      return await RolePermission.getRolePermissionCount(roleObjectId);
    } catch (error) {
      throw error;
    }
  }

  /**
   * 查找所有角色权限关联（支持分页和筛选）
   * @param criteria 筛选条件
   * @param options 分页和排序选项
   * @returns 角色权限关联列表和分页信息
   */
  async findAll(
    criteria: {
      roleId?: mongoose.Types.ObjectId | string;
      permissionId?: mongoose.Types.ObjectId | string;
      systemId?: mongoose.Types.ObjectId | string;
      status?: number;
    } = {},
    options: {
      page?: number;
      limit?: number;
      sort?: string;
      select?: string;
    } = {}
  ): Promise<{ rolePermissions: IRolePermissionDocument[]; total: number; page: number; totalPages: number }> {
    try {
      const {
        roleId,
        permissionId,
        systemId,
        status = 1
      } = criteria;
      
      const {
        page = 1,
        limit = 10,
        sort = '-createdAt',
        select
      } = options;
      
      // 验证状态值
      if (typeof status === 'number' && ![0, 1].includes(status)) {
        throw new Error('无效的状态值');
      }
      
      // 构建查询条件
      const query: any = { status };
      
      if (roleId) {
        if (!mongoose.Types.ObjectId.isValid(roleId)) {
          throw new Error('无效的角色ID');
        }
        query.roleId = typeof roleId === 'string' ? new mongoose.Types.ObjectId(roleId) : roleId;
      }
      
      if (permissionId) {
        if (!mongoose.Types.ObjectId.isValid(permissionId)) {
          throw new Error('无效的权限ID');
        }
        query.permissionId = typeof permissionId === 'string' ? new mongoose.Types.ObjectId(permissionId) : permissionId;
      }
      
      if (systemId) {
        if (!mongoose.Types.ObjectId.isValid(systemId)) {
          throw new Error('无效的系统ID');
        }
        query.systemId = typeof systemId === 'string' ? new mongoose.Types.ObjectId(systemId) : systemId;
      }
      
      // 计算跳过的文档数量
      const skip = (page - 1) * limit;
      
      // 构建查询
      let queryBuilder = RolePermission.find(query)
        .populate('roleId')
        .populate('permissionId')
        .populate('systemId')
        .populate('assignedBy')
        .sort(sort)
        .skip(skip)
        .limit(limit);
      
      if (select) {
        queryBuilder = queryBuilder.select(select);
      }
      
      // 执行查询
      const [rolePermissions, total] = await Promise.all([
        queryBuilder.exec(),
        RolePermission.countDocuments(query)
      ]);
      
      const totalPages = Math.ceil(total / limit);
      
      return {
        rolePermissions,
        total,
        page,
        totalPages
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 清理过期的角色权限关联
   * @returns 清理的数量
   */
  async cleanupExpiredPermissions(): Promise<number> {
    try {
      const result = await RolePermission.updateMany(
        {
          expiresAt: { $lt: new Date() },
          status: 1
        },
        {
          status: 0,
          updatedAt: new Date()
        }
      );
      
      return result.modifiedCount;
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取即将过期的角色权限关联
   * @param days 天数
   * @returns 即将过期的角色权限关联数组
   */
  async getExpiringPermissions(days: number): Promise<IRolePermissionDocument[]> {
    try {
      if (typeof days !== 'number' || days < 0) {
        throw new Error('Days must be a non-negative number');
      }
      
      const expiryDate = new Date();
      expiryDate.setDate(expiryDate.getDate() + days);
      
      return await RolePermission.find({
        expiresAt: {
          $exists: true,
          $ne: null,
          $lte: expiryDate,
          $gt: new Date()
        },
        status: 1
      })
      .populate('roleId')
      .populate('permissionId')
      .populate('systemId')
      .populate('assignedBy')
      .sort({ expiresAt: 1 });
    } catch (error) {
      throw error;
    }
  }
}

export default RolePermissionDAO;